#include "acceptor.h"
#include "inet_address.h"
#include "logger.h"

#include <cerrno>
#include <endian.h>
#include <cerrno>
#include <functional>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>

static int create_nonblocking() {
    int sockfd = ::socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, IPPROTO_TCP);
    if (sockfd < 0) {
        LOG_FATAL("%s:%s:%d listen socket create err:%d \n", __FILE__, __FUNCTION__, __LINE__,
                  errno);
    }
    return sockfd;
}

Acceptor::Acceptor(EventLoop *loop, const InetAddress &listen_addr, bool reuseport)
    : loop_(loop), accept_socket_(create_nonblocking()) // socket
      ,accept_channel_(loop, accept_socket_.fd()), listenning_(false) {
    accept_socket_.set_reuse_addr(true);
    accept_socket_.set_reuse_port(true);
    accept_socket_.bind_address(listen_addr); // bind
    // TcpServer::start() Acceptor.listen
    // 有新用户的连接，要执行回调,要执行一个回调 connfd=> channel=> subloop
    // base_loop => accept_channel_(listenfd)
    accept_channel_.set_read_callback(std::bind(&Acceptor::handle_read, this));
}
Acceptor::~Acceptor() {
    accept_channel_.disable_all();
    accept_channel_.remove();
}

void Acceptor::listen() {
    listenning_ = true;
    accept_socket_.listen();          // listen
    accept_channel_.enable_reading(); // accept_channel_=>Poller
}

// listenfd有事件发生了，就是有新用户连接了
void Acceptor::handle_read() {
    InetAddress peeraddr;
    int connfd = accept_socket_.accept(&peeraddr);
    if (connfd >= 0) {
        if (new_connection_callback_) {
            new_connection_callback_(connfd,
                                     peeraddr); // 轮询找到subloop,唤醒，分发当前客户端的channel
        } else {
            ::close(connfd);
        }
    } else {
        LOG_ERROR("%s:%s:%d accept err:%d \n", __FILE__, __FUNCTION__, __LINE__, errno);
        if (errno == EMFILE) {
            LOG_ERROR("%s:%s:%d sockfd reached limit \n", __FILE__, __FUNCTION__, __LINE__);
        }
    }
}